// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.settings.feeds

import android.content.Context
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import xyz.apiote.bimba.czwek.api.Error
import xyz.apiote.bimba.czwek.repo.FeedInfo
import xyz.apiote.bimba.czwek.repo.OfflineRepository
import xyz.apiote.bimba.czwek.repo.OnlineRepository
import xyz.apiote.bimba.czwek.repo.TrafficResponseException
import xyz.apiote.bimba.czwek.repo.join

class FeedsViewModel : ViewModel() {
	private val _settings = MutableLiveData<FeedsSettings>()
	val settings: LiveData<FeedsSettings> = _settings

	private val _feeds = MutableLiveData<Map<String, FeedInfo>>()
	val feeds: LiveData<Map<String, FeedInfo>> = _feeds

	private val _error = MutableLiveData<Error>()
	val error: LiveData<Error> = _error

	fun loadSettings(context: Context) {
		_settings.value = FeedsSettings.load(context)
	}

	fun setSettings(feedID: String, feedSettings: FeedSettings) {
		val feedsSettings = _settings.value ?: FeedsSettings(mutableMapOf())
		feedsSettings.settings[feedID] = feedSettings
		_settings.value = feedsSettings
	}

	fun setEnabled(feedID: String, enabled: Boolean) {
		val feedSettings = (_settings.value ?: FeedsSettings(mutableMapOf())).settings[feedID]
		setSettings(feedID, feedSettings?.copy(enabled = enabled) ?: FeedSettings(enabled, true))
	}

	fun loadFeeds(context: Context) {
		MainScope().launch {
			val offlineRepository = OfflineRepository()
			val offlineFeeds =
				offlineRepository.getFeeds(context)
			if (!offlineFeeds.isNullOrEmpty()) {
				_feeds.value = offlineFeeds
			}
			try {
				val repository = OnlineRepository()
				val onlineFeeds =
					repository.getFeeds(context)
				joinFeeds(offlineFeeds, onlineFeeds).let { joinedFeeds ->
					_feeds.value = joinedFeeds
				}
			} catch (e: TrafficResponseException) {
				if (offlineFeeds.isNullOrEmpty()) {
					_error.value = e.error
				}
				Log.e("Feeds", "$e")
			}
		}
	}

	private fun joinFeeds(
		feeds1: Map<String, FeedInfo>?,
		feeds2: Map<String, FeedInfo>?
	): Map<String, FeedInfo> {
		if (feeds1.isNullOrEmpty() && feeds2.isNullOrEmpty()) {
			return emptyMap()
		}

		if (feeds1.isNullOrEmpty()) {
			return feeds2!!
		}
		if (feeds2.isNullOrEmpty()) {
			return feeds1
		}

		return feeds1.keys.union(feeds2.keys).associateWith { feeds1[it].join(feeds2[it]) }
	}
}
